package com.prj.ufdm.cloud.ms.core.bpo._impl;

import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.prj.ufdm.cloud.base.exception.BaseException;
import com.prj.ufdm.cloud.base.util.BaseDateUtil;
import com.prj.ufdm.cloud.base.util.BaseUuidUtil;
import com.prj.ufdm.cloud.ms.core.bpo.SeqNumBPO;
import com.prj.ufdm.cloud.ms.core.dao.SeqNumDao;
import com.prj.ufdm.cloud.ms.core.enums.CodeGenerateEnum;
import com.prj.ufdm.cloud.ms.core.model.SeqNum;

@Service(value="seqNumBPO")
public class SeqNumBPOImpl implements SeqNumBPO {
	
	@Autowired
	private SeqNumDao seqNumDao;
	
	//防止数据库中删除重新获取的问题,重启失效
	private static ConcurrentMap<String, String> map=new ConcurrentHashMap<String, String>();
	

	/**
	 * 不支持分包部署的分布式，如果要分布式则需根据redis生成
	 */
	@Override
	public synchronized String generateCode(SeqNum s) throws Exception {
		if(StringUtils.isBlank(s.getCodeType())) {
			throw new BaseException("类型不能为空，生成失败！");
		}
		String codeType=s.getCodeType();
		//默认值：年月日时分秒+code
		String code=CodeGenerateEnum.getRetValue(codeType);
		if(StringUtils.isBlank(code)) {
			throw new BaseException("枚举中未配置该默认值，生成失败！");
		}
		SeqNum seqNum=new SeqNum();
		seqNum.setId(BaseUuidUtil.getUUID());
		seqNum.setCodeType(codeType);
		SeqNum sysCode=seqNumDao.selectByCodeType(codeType);
		String oldValue=map.get(codeType);
		if(StringUtils.isBlank(oldValue)) {
			if(sysCode==null || "0".equals(sysCode.getCodeValue())) {
				//保存值
				seqNum.setCodeValue(code);
				seqNumDao.insertOne(seqNum);
			}else {
				code=String.valueOf(Integer.valueOf(sysCode.getCodeValue())+1);
				seqNum.setCodeValue(code);
				seqNumDao.updateByCodeType(seqNum);
			}
			//如果当前缓存中不存在值，则赋值
//			map.put(codeType, code);
		}else {
			//如果缓存中有值，但是数据库中没值
			if(sysCode==null || "0".equals(sysCode.getCodeValue())) {
				//保存数据库的值为缓存中的值+1，给map设置新值
				code=String.valueOf(Integer.valueOf(oldValue)+1);
				seqNum.setCodeValue(code);
				seqNumDao.insertOne(seqNum);
			}else {
				//缓存有值数据库也有值，此时对比数据库中的值与缓存中的值取大的加1，因为数据库可能随时被人改动
				String newValue=String.valueOf(Math.max(Integer.valueOf(oldValue),Integer.valueOf(sysCode.getCodeValue()))); 
				code=String.valueOf(Integer.valueOf(newValue)+1);
				seqNum.setCodeValue(code);
				seqNumDao.updateByCodeType(seqNum);
			}
			//设置新值
//			map.put(codeType, code);
		}
		//设置新值
		map.put(codeType, code);
		String com="";
		if(s.isDefaultValue()) {
			//使用默认值
			//默认年月日时分秒+编码
			com=BaseDateUtil.dateToString(new Date(), "yyyyMMddHHmmss");
		}else {
			if(!StringUtils.isBlank(s.getCodeParams())) {
				//自定义规则
				com=s.getCodeParams();
			}
		}
		return com+map.get(codeType);
	}
	
//	public static void main(String[] args) {
//		System.out.println(100001%10000);
//	}

}
